// 测试服务器：
var express = require('express');
var app = express();
var multer = require('multer');
var fs = require('fs');
var path = require('path');
// 获取当前目录的上一级目录
var uploadsPath = path.resolve(__dirname, '../uploads');
app.use(express.json());
app.listen(3000, function () {
    console.log('Example app listening on port 3000!');
});

// hello world
app.get('/', function (req, res) {
    res.send('Hello World!');
});
// 允许跨域
app.all('*', function (req, res, next) {
    // console.log(req.method, req.url)
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With');
    res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
    if (req.method == 'OPTIONS') {
        res.sendStatus(200);
    } else {
        next();
    }
});
// 分片上传接口
var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, uploadsPath)
    },
    filename: function (req, file, cb) {
        // 分片上传逻辑，检查参数里面的主文件md5值
        var md5 = req.body.md5;
        var filename = req.body.filename;
        var chunkIndex = req.body.chunkIndex;
        // 写到文件 md5 + chunkIndex
        cb(null, md5 + '-' + chunkIndex + '-' + filename);
    }
})
var upload = multer({ storage: storage })
app.post('/upload', upload.single('file'), function (req, res, next) {
    // 分片上传逻辑，检查参数里面的主文件md5值
    var md5 = req.body.md5;
    var filename = req.body.filename;
    var chunkIndex = req.body.chunkIndex;
    var chunkCount = req.body.chunkCount;
    // 写到文件 md5 + chunkIndex
    res.json({
        code: 0,
        data: {
            md5: md5,
            filename: filename,
            chunkIndex: chunkIndex,
            chunkCount: chunkCount
        }
    });
});
app.post('/merge', function (req, res) {
    var md5 = req.body.md5;
    var filename = req.body.filename;
    var chunkCount = req.body.chunkCount;
    // 合并文件
    var filePath = path.resolve(uploadsPath, md5 + '-' + filename);
    var writeStream = fs.createWriteStream(filePath);

    writeStream.on('error', err => {
        console.error('WriteStream error:', err);
        res.status(500).json({ error: 'Internal server error' });
    });

    var mergePromises = [];
    var lastPromise = Promise.resolve();

    for (let i = 0; i < chunkCount; i++) {
        lastPromise = lastPromise.then(() => {
            return new Promise((resolve, reject) => {
                var chunkFilePath = path.resolve(uploadsPath, md5 + '-' + i + '-' + filename);
                var readStream = fs.createReadStream(chunkFilePath);

                readStream.on('error', err => reject(err));
                readStream.on('end', () => {
                    resolve();
                });

                readStream.pipe(writeStream, { end: false });
                // console.log("合并文件", chunkFilePath);
            });
        });

        mergePromises.push(lastPromise);
    }

    Promise.all(mergePromises)
        .then(() => {
            writeStream.end();
            for (var i = 0; i < chunkCount; i++) {
                var chunkFilePath = path.resolve(uploadsPath, md5 + '-' + i + '-' + filename);
                fs.unlink(chunkFilePath, function (err) {
                    if (err) {
                        console.error('Error deleting chunk file:', err);
                    }
                });
            }
            res.json({
                code: 0,
                data: {
                    md5: md5,
                    filename: md5 + "-" + filename,
                    chunkCount: chunkCount
                }
            });
        })
        .catch(err => {
            console.error('Error merging chunks:', err);
            res.status(500).json({ error: 'Internal server error' });
        });
});


// 查询当前文件已经上传的分片，后续可以断点续传
app.all('/check', function (req, res) {
    var md5 = req.body.md5;
    var filename = req.body.filename;
    // 遍历文件夹，找出符合md5-chunkIndex-filename的文件，取最大的chunkIndex为返回值
    var dirPath = 'uploads/';
    var chunkIndex = 0;
    var files = fs.readdirSync(dirPath);
    files.forEach(function (file) {
        var reg = new RegExp(md5 + '-(\\d+)-' + filename);
        var result = reg.exec(file);
        if (result) {
            chunkIndex = Math.max(chunkIndex, parseInt(result[1]));
        }
    });
    res.json({
        code: 0,
        data: {
            md5: md5,
            filename: filename,
            chunkIndex: chunkIndex
        }
    });
});